<script setup lang="ts">
import { groupBy } from 'xe-utils'
import { Message } from '@arco-design/web-vue'
import { ResourceApi, RoleApi } from '@/apis'
import type { TableInstanceColumns } from '@/components/ProTable/type'
import { useRequest, useTable } from '@/hooks'

const props = defineProps<{
  role?: RoleApi.RoleResp
}>()

// 所有模块全选
const allModuleSelected = ref(false)
// 模块半选
const moduleIndeterminate = ref(false)
// 编辑禁用，超级管理员不能编辑
const editDisabled = computed(() => {
  return props.role?.preserved
})

const {
  loading: roleResourceLoading,
  response: roleResourceList,
  refresh: refreshRoleResource,
} = useRequest(() => RoleApi.getRoleResourceCodeList(props.role!.id), false)

// 资源表格数据
const {
  tableData: resourceTableData,
  loading: resourceLoading,
} = useTable(() => {
  return ResourceApi.getList({}).then((resourceList) => {
    const resourceGroup = groupBy(resourceList, 'module')
    return Object.keys(resourceGroup).map((module) => {
      return {
        module,
        resourceList: resourceGroup[module],
        allSelected: false,
        indeterminate: false,
      }
    })
  })
})
const columns: TableInstanceColumns[] = [
  {
    title: '模块',
    slotName: 'module',
    width: 120,
    ellipsis: true,
    tooltip: true,
    fixed: 'left',
  },
  { title: '资源列表', dataIndex: 'resourceList', slotName: 'resourceList' },
  {
    title: '操作',
    slotName: 'action',
    titleSlotName: 'actionHeader',
    width: 100,
    align: 'center',
    fixed: 'right',
  },
]

// 资源管理
const router = useRouter()
const onManageResource = () => {
  router.push({ path: '/develop/common/resource' })
}

// 资源表单
const onSaveRoleResource = () => {
  const roleResourceList: string[] = []
  resourceTableData.value.forEach((resourceGroup) => {
    resourceGroup.resourceList.forEach((resource) => {
      if (resource.selected) {
        roleResourceList.push(resource.id)
      }
    })
  })
  const data = {
    roleId: props.role?.id,
    resourceList: roleResourceList,
  }
  RoleApi.updateRoleResource(data).then(() => {
    Message.success('保存成功')
  })
}

// 更新单个模块状态
const updateSingleModuleStatus = (index) => {
  const currentGroup = resourceTableData.value[index]
  currentGroup.allSelected = !currentGroup.resourceList.some(item => !item.selected)
  currentGroup.indeterminate = !currentGroup.allSelected && currentGroup.resourceList.some(item => item.selected)
}

// 更新所有模块全选状态
const updateAllModuleStatus = () => {
  allModuleSelected.value = !resourceTableData.value.some(item => !item.allSelected)
  moduleIndeterminate.value = !allModuleSelected.value && resourceTableData.value.some(item => (item.allSelected || item.indeterminate))
}

// 单个资源选中
const onChangeResource = (selected, index) => {
  updateSingleModuleStatus(index)
  updateAllModuleStatus()
}

// 单个模块选中
const onSelectSingleModule = (selected, rowIndex) => {
  const resourceGroup = resourceTableData.value[rowIndex]
  resourceGroup.resourceList.forEach(resource => resource.selected = selected)
  resourceGroup.allSelected = selected
  resourceGroup.indeterminate = false
  updateAllModuleStatus()
}

// 所有模块选中
const onSelectAllModule = (selected) => {
  resourceTableData.value.forEach((resourceGroup) => {
    resourceGroup.resourceList.forEach(resource => resource.selected = selected)
    resourceGroup.allSelected = selected
    resourceGroup.indeterminate = false
  })
  allModuleSelected.value = selected
  moduleIndeterminate.value = false
}

watch(() => props.role, (newRole) => {
  if (!newRole || !newRole.id) {
    return
  }
  refreshRoleResource()
})

watch(() => roleResourceList, () => {
  const roleResourceSet = new Set<string>(roleResourceList.value)
  resourceTableData.value.forEach((resourceGroup) => {
    let someSelected = false
    let allSelected = true
    resourceGroup.resourceList.forEach((resource) => {
      resource.selected = roleResourceSet.has('*') || roleResourceSet.has(resource.code)
      if (resource.selected) {
        someSelected = true
      } else {
        allSelected = false
      }
    })
    resourceGroup.allSelected = allSelected
    resourceGroup.indeterminate = !allSelected && someSelected
  })
  updateAllModuleStatus()
}, { deep: true })
</script>

<template>
  <ProTable
    row-key="module"
    :data="resourceTableData"
    :columns="columns"
    :loading="resourceLoading || roleResourceLoading"
    :pagination="false"
    :bordered="{ cell: true }"
    :disabled-tools="['size']"
  >
    <template #toolbar-left>
      <div>
        <icon-info-circle-fill style="color: rgb(var(--primary-6));" />
        通过勾选资源列表，为角色绑定权限
        <a-button v-permission="['system:resource:manage']" type="text" size="medium" @click="onManageResource">
          <span>管理资源</span>
        </a-button>
      </div>
    </template>
    <template #toolbar-right>
      <a-button v-permission="['system:org:manage']" type="primary" size="medium" :disabled="editDisabled" @click="onSaveRoleResource">
        <span>保存权限</span>
      </a-button>
    </template>
    <template #actionHeader>
      <a-checkbox v-model="allModuleSelected" :disabled="editDisabled" :indeterminate="moduleIndeterminate" @change="onSelectAllModule($event)" />
    </template>
    <template #module="{ record }">
      <CellDict :value="record.module" code="ResourceModule" />
    </template>
    <template #resourceList="{ record, rowIndex }">
      <a-grid :cols="4" :col-gap="24" :row-gap="16">
        <a-grid-item v-for="resource of record.resourceList" :key="resource.value">
          <a-tooltip :content="resource.description || resource.name">
            <a-checkbox v-model="resource.selected" :disabled="editDisabled" @change="onChangeResource($event, rowIndex)">
              {{ resource.name }}
            </a-checkbox>
          </a-tooltip>
        </a-grid-item>
      </a-grid>
    </template>
    <template #action="{ record, rowIndex }">
      <a-checkbox v-model="record.allSelected" :disabled="editDisabled" :indeterminate="record.indeterminate" @change="onSelectSingleModule($event, rowIndex)" />
    </template>
  </ProTable>
</template>

<style scoped>

</style>
